'use strict'

process.chdir(__dirname)

const titbit = require('titbit')
const fs = require('fs')
const dbcfg = require('./dbconfig.js')
const pg = require('pg')
const wxkey = require('./wxkey.js')
const {httpcli} = require('gohttp')
const token = require('titbit-token')
const tbloader = require('titbit-loader')



try{
    fs.accessSync('./images')
}catch(err){
    fs.mkdirSync('./images')
}

let psql = new pg.Pool(dbcfg)

let cert_path = '/usr/local/share'

const app = new titbit({
    //开启调试模式，若有错误会输出错误信息
    debug: true,
    globalLog: true,
    cert: `${cert_path}/api.52h5.xyz.pem`,
    key: `${cert_path}/api.52h5.xyz.key`
})

let tb = new tbloader();
tb.init(app);

app.addService('psql',psql)

app.get('/', async c => {
    c.send('ok')
})

/**----------------content路由----------------*/
//获取内容列表
app.get('/content', async c => {
    let ret = await psql.query(`select * from content`)
    c.send(ret.rows)//等效于c.res.body = ret.rows
})
//content路由end

//获取具体内容
app.get('/content/:id', async c => {
    let sqltext = `SELECT * FROM content WHERE id=$1`
    let r = await c.service.psql.query(sqltext, [c.param.id])

    if(r.rowCount === 0){
        return c.status(404).send('content not found')
    }

    c.send(r.rows[0])
})

app.post('/content', async c => {
    try{
        //提交的Body数据通过c.body获取
        let data = JSON.parse(c.body)

        let sqltext = `INSERT INTO` 
                    + ` content(id, add_time, detail, title, update_time)`
                    + ' VALUES ($1, $2, $3, $4, $5)'

        //生成唯一ID
        let id = c.helper.makeId()
        let tm = Date.now()

        let r = await psql.query(sqltext, [
            id, tm, data.detail, data.title, tm
        ])

        if(r.rowCount === 0){
            return c.status(500).send('failed')
        }

        c.send(id)

    }catch(err){
        c.status(404).send('it is not json data')
    }
})

/**---------------content路由-END --------------- */

app.get('/upload', async c=>{
    //c.reply是响应对象，可写的流
    //在HTTP1.1中指向response，在HTTP2中指向http2stream
    await c.helper.pipe('./upload.html', c.reply)
})

app.post('/upload', async c=>{
    //根据name获取文件对象
    let f = c.getFile('image')

    if(!f){
        return c.status(400).send('image not found')
    }

    //根据传入的原始文件生成唯一文件名，主要使用f.filename的扩展名
    let fname = c.helper.makeName(f.filename)

    //移动文件到指定位置
    await c.moveFile(f, `./image/${fname}`)
    c.send(fname)
})

app.get('/static/*', async c=>{

})

//返回图片数据
app.get('/image/:name', async c => {
    //c.param是一个对象，其中的key值是路由参数的名称
    let imgname = c.param.name;

    await c.helper.pipe(`./image/${imgname}`, c.reply)
})

let tok = new token({
    expires: 45,
//32位
    key: '01234567890123456789012345678901',
//16位
    iv:'0123456789012345'
})

app.get('/mp-login/:code', async c =>{
    let auth_url = `https://api.weixin.qq.com/sns/jscode2session`
        +`?appid=${wxkey.appid}`
        +`&secret=${wxkey.secret}`
        +`&js_code=${c.param.code}`
        +`&grant_type=authorization_code`

    let ret = await httpcli.get(auth_url).then(res => {
        return res.json()
    })

    c.send(tok.make(ret))
})

app.get('/decrypt/:token', async c => {
    c.send( tok.verify(c.param.token) )
})

//运行在1234端口
app.run(2004)

/**
 * HTTP 消息头 content-type 指定了数据的类型（数据的格式）
 * Client 
 *      content-type描述的值
 *      要和提交的Body数据一致。
 * Server
 *      根据content-type的值决定如何解析Body数据
    * content-type:
    *      multipart/form-data;boundary=***    ------  文件解析
    *      text/*              ----------------------  文件类型
    *      application/*       ----------------------  要看具体值，application/json也是文本类型
    *      ......              ----------------------  每种类型如何处理是双方设计好的沟通方式
 * 到web框架这一层面，则如何处理是开发框架设计好的，但通常都要遵循一个原则：
 *      允许开发者做自己的处理
 * 
 * 在本框架范围内
 *      multipart类型 c.body是object类型，文件信息解析到c.files。
 *      application/x-www-form-urlencoded 传统的表单类型，c.body = c.rowBody.toString('utf-8')。
 *      其他类型： c.body 是buffer类型，就是对c.rawBody的引用。
 */